package com.roger.homecenterscreen.data.location

import android.annotation.SuppressLint
import android.content.Context
import android.location.Address
import android.location.Geocoder
import android.location.Location
import android.location.LocationListener
import android.location.LocationManager
import android.os.Bundle
import android.os.Looper
import kotlinx.coroutines.suspendCancellableCoroutine
import kotlinx.coroutines.withTimeoutOrNull
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import java.util.Locale
import kotlin.coroutines.resume
import kotlin.coroutines.resumeWithException
import com.roger.homecenterscreen.data.network.NetworkModule
import com.roger.homecenterscreen.config.ApiConfig
import android.util.Log

class LocationService(private val context: Context) {
    
    companion object {
        private const val TAG = "LocationService"
    }
    
    private val locationManager: LocationManager =
        context.getSystemService(Context.LOCATION_SERVICE) as LocationManager
    
    private val ipLocationHelper = IpLocationHelper()
    
    /**
     * 获取当前位置
     * @return LocationData 包含经纬度信息
     */
    @SuppressLint("MissingPermission")
    suspend fun getCurrentLocation(): Result<LocationData> {
        return try {
            // 检查位置服务是否可用
            if (!isLocationEnabled()) {
                return Result.failure(Exception("位置服务未开启"))
            }
            
            // 优先使用GPS，如果不可用则使用网络定位
            val provider = when {
                locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER) -> 
                    LocationManager.GPS_PROVIDER
                locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER) -> 
                    LocationManager.NETWORK_PROVIDER
                else -> return Result.failure(Exception("没有可用的位置提供者"))
            }
            
            val location = withTimeoutOrNull(15000L) { // 15秒超时
                suspendCancellableCoroutine<Location> { continuation ->
                    val locationListener = object : LocationListener {
                        override fun onLocationChanged(location: Location) {
                            locationManager.removeUpdates(this)
                            continuation.resume(location)
                        }
                        
                        override fun onProviderEnabled(provider: String) {}
                        override fun onProviderDisabled(provider: String) {
                            locationManager.removeUpdates(this)
                            continuation.resumeWithException(Exception("位置提供者已禁用: $provider"))
                        }
                        override fun onStatusChanged(provider: String?, status: Int, extras: Bundle?) {}
                    }
                    
                    continuation.invokeOnCancellation {
                        locationManager.removeUpdates(locationListener)
                    }
                    
                    try {
                        locationManager.requestLocationUpdates(
                            provider,
                            0L, // 最小时间间隔
                            0f, // 最小距离间隔
                            locationListener,
                            Looper.getMainLooper()
                        )
                    } catch (e: Exception) {
                        continuation.resumeWithException(e)
                    }
                }
            }
            
            if (location != null) {
                val locationData = LocationData(
                    latitude = location.latitude,
                    longitude = location.longitude
                )
                
                // 尝试获取地名信息
                val enrichedLocation = getAddressFromLocation(locationData)
                Result.success(enrichedLocation)
            } else {
                Result.failure(Exception("获取位置超时"))
            }
        } catch (e: Exception) {
            Result.failure(e)
        }
    }
    
    /**
     * 获取最后已知位置（更快但可能不准确）
     */
    @SuppressLint("MissingPermission")
    suspend fun getLastKnownLocation(): Result<LocationData> {
        return try {
            if (!isLocationEnabled()) {
                return Result.failure(Exception("位置服务未开启"))
            }
            
            // 尝试从多个提供者获取最后已知位置
            val providers = listOf(
                LocationManager.GPS_PROVIDER,
                LocationManager.NETWORK_PROVIDER,
                LocationManager.PASSIVE_PROVIDER
            )
            
            var bestLocation: Location? = null
            
            for (provider in providers) {
                if (locationManager.isProviderEnabled(provider)) {
                    val location = locationManager.getLastKnownLocation(provider)
                    if (location != null && isBetterLocation(location, bestLocation)) {
                        bestLocation = location
                    }
                }
            }
            
            if (bestLocation != null) {
                val locationData = LocationData(
                    latitude = bestLocation.latitude,
                    longitude = bestLocation.longitude
                )
                
                // 尝试获取地名信息
                val enrichedLocation = getAddressFromLocation(locationData)
                Result.success(enrichedLocation)
            } else {
                Result.failure(Exception("没有最后已知位置"))
            }
        } catch (e: Exception) {
            Result.failure(e)
        }
    }
    
    /**
     * 持续监听位置变化
     */
    @SuppressLint("MissingPermission")
    fun startLocationUpdates(
        callback: (LocationData) -> Unit,
        onError: (Exception) -> Unit
    ): LocationListener {
        if (!isLocationEnabled()) {
            onError(Exception("位置服务未开启"))
            return object : LocationListener {
                override fun onLocationChanged(location: Location) {}
                override fun onProviderEnabled(provider: String) {}
                override fun onProviderDisabled(provider: String) {}
                override fun onStatusChanged(provider: String?, status: Int, extras: Bundle?) {}
            }
        }
        
        val locationListener = object : LocationListener {
            override fun onLocationChanged(location: Location) {
                // 异步获取地名信息
                GlobalScope.launch(Dispatchers.IO) {
                    val locationData = LocationData(
                        latitude = location.latitude,
                        longitude = location.longitude
                    )
                    val enrichedLocation = getAddressFromLocation(locationData)
                    
                    // 在主线程回调
                    launch(Dispatchers.Main) {
                        callback(enrichedLocation)
                    }
                }
            }
            
            override fun onProviderEnabled(provider: String) {
                // 位置提供者启用
            }
            
            override fun onProviderDisabled(provider: String) {
                onError(Exception("位置提供者已禁用: $provider"))
            }
            
            override fun onStatusChanged(provider: String?, status: Int, extras: Bundle?) {
                // 位置提供者状态变化
            }
        }
        
        try {
            // 优先使用GPS，如果不可用则使用网络定位
            val provider = when {
                locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER) -> 
                    LocationManager.GPS_PROVIDER
                locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER) -> 
                    LocationManager.NETWORK_PROVIDER
                else -> {
                    onError(Exception("没有可用的位置提供者"))
                    return locationListener
                }
            }
            
            locationManager.requestLocationUpdates(
                provider,
                10000L, // 10秒更新一次
                100f,   // 移动100米才更新
                locationListener,
                Looper.getMainLooper()
            )
        } catch (e: Exception) {
            onError(e)
        }
        
        return locationListener
    }
    
    /**
     * 停止位置更新
     */
    fun stopLocationUpdates(locationListener: LocationListener) {
        locationManager.removeUpdates(locationListener)
    }
    
    /**
     * 根据坐标获取地址信息
     */
    private suspend fun getAddressFromLocation(location: LocationData): LocationData = withContext(Dispatchers.IO) {
        return@withContext try {
            // 优先使用聚合数据API
            val juheResult = getAddressFromJuheApi(location)
            if (juheResult.city.isNotEmpty()) {
                return@withContext juheResult
            }
            
            // 备用方案1：使用Android Geocoder
            val geocoder = Geocoder(context, Locale.CHINA)
            
            // Android API level 33+ 使用新的异步方法
            val geocoderResult = if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.TIRAMISU) {
                suspendCancellableCoroutine { continuation ->
                    geocoder.getFromLocation(
                        location.latitude,
                        location.longitude,
                        1
                    ) { addresses ->
                        if (addresses.isNotEmpty()) {
                            val address = addresses[0]
                            continuation.resume(parseAddress(location, address))
                        } else {
                            continuation.resume(location) // 返回原始位置数据
                        }
                    }
                    
                    continuation.invokeOnCancellation {
                        // 取消操作，返回原始位置数据
                    }
                }
            } else {
                // 使用旧的同步方法
                @Suppress("DEPRECATION")
                val addresses = geocoder.getFromLocation(location.latitude, location.longitude, 1)
                if (!addresses.isNullOrEmpty()) {
                    parseAddress(location, addresses[0])
                } else {
                    location
                }
            }
            
            if (geocoderResult.city.isNotEmpty()) {
                return@withContext geocoderResult
            }
            
            // 备用方案2：使用坐标范围判断
            location.copy(
                city = getCityFromCoordinates(location.latitude, location.longitude),
                district = "",
                address = "GPS定位"
            )
        } catch (e: Exception) {
            // 如果所有方法都失败，使用坐标备用方案
            location.copy(
                city = getCityFromCoordinates(location.latitude, location.longitude),
                district = "",
                address = "GPS定位"
            )
        }
    }
    
    /**
     * 使用混合IP地址查询服务获取地址信息
     */
    private suspend fun getAddressFromJuheApi(location: LocationData): LocationData {
        return try {
            // 方案1：优先尝试聚合数据IP地址查询API（如果有配置API Key）
            if (ApiConfig.JUHE_IP_API_KEY != "your_juhe_ip_api_key_here") {
                val juheResult = getLocationFromJuheAPI()
                if (juheResult.city.isNotEmpty()) {
                    return juheResult.copy(
                        latitude = location.latitude,
                        longitude = location.longitude
                    )
                }
            }
            
            // 方案2：使用免费IP地址查询服务作为备用
            val ipLocationResult = ipLocationHelper.getCurrentLocationByIP()
            
            if (ipLocationResult.isSuccess) {
                val ipLocation = ipLocationResult.getOrNull()
                if (ipLocation != null && ipLocation.city.isNotEmpty()) {
                    // 如果IP查询到的位置有效，则使用IP查询结果
                    // 但保留GPS的精确坐标
                    location.copy(
                        city = ipLocation.city,
                        district = ipLocation.district,
                        address = ipLocation.address
                    )
                } else {
                    location // IP查询无效，返回原始位置
                }
            } else {
                location // IP查询失败，返回原始位置
            }
        } catch (e: Exception) {
            Log.e(TAG, "获取IP地址位置信息失败", e)
            location // 异常时返回原始位置
        }
    }
    
    /**
     * 使用聚合数据IP地址查询API
     */
    private suspend fun getLocationFromJuheAPI(): LocationData {
        return try {
            // 先获取当前公网IP
            val ipResult = getCurrentPublicIP()
            if (ipResult.isFailure) {
                return LocationData(0.0, 0.0) // IP获取失败
            }
            
            val ip = ipResult.getOrNull() ?: return LocationData(0.0, 0.0)
            
            // 使用聚合数据IP地址查询
            val response = NetworkModule.locationApiService.getLocationByIP(
                ip = ip,
                key = ApiConfig.JUHE_IP_API_KEY
            )
            
            if (response.isSuccessful) {
                val body = response.body()
                if (body?.error_code == 0 && body.result != null) {
                    val result = body.result!!
                    LocationData(
                        latitude = 0.0, // 聚合数据IP查询不返回坐标
                        longitude = 0.0,
                        city = result.City ?: "",
                        district = result.Province ?: "",
                        address = "${result.Country ?: ""} ${result.Province ?: ""} ${result.City ?: ""}"
                    )
                } else {
                    LocationData(0.0, 0.0) // 查询失败
                }
            } else {
                LocationData(0.0, 0.0) // 请求失败
            }
        } catch (e: Exception) {
            LocationData(0.0, 0.0) // 异常
        }
    }
    
    /**
     * 获取当前设备的公网IP地址（简化版）
     */
    private suspend fun getCurrentPublicIP(): Result<String> = withContext(Dispatchers.IO) {
        return@withContext try {
            val client = okhttp3.OkHttpClient.Builder()
                .connectTimeout(5, java.util.concurrent.TimeUnit.SECONDS)
                .readTimeout(5, java.util.concurrent.TimeUnit.SECONDS)
                .build()
            
            val request = okhttp3.Request.Builder()
                .url("https://api.ipify.org")
                .build()
            
            val response = client.newCall(request).execute()
            
            if (response.isSuccessful) {
                val ip = response.body?.string()?.trim()
                if (!ip.isNullOrBlank()) {
                    Result.success(ip)
                } else {
                    Result.failure(Exception("IP地址为空"))
                }
            } else {
                Result.failure(Exception("获取IP失败"))
            }
        } catch (e: Exception) {
            Result.failure(e)
        }
    }
    
    /**
     * 解析地址信息
     */
    private fun parseAddress(location: LocationData, address: Address): LocationData {
        // 尝试多种方式获取城市名称
        val city = address.locality 
            ?: address.adminArea 
            ?: address.subAdminArea 
            ?: getCityFromCoordinates(location.latitude, location.longitude)
            
        val district = address.subLocality 
            ?: address.thoroughfare 
            ?: ""
            
        val fullAddress = address.getAddressLine(0) ?: ""
        
        return location.copy(
            city = city,
            district = district,
            address = fullAddress
        )
    }
    
    /**
     * 根据坐标获取城市名称（备用方案）
     */
    private fun getCityFromCoordinates(lat: Double, lon: Double): String {
        return when {
            // 北京范围 (39.4-41.6, 115.7-117.4)
            lat in 39.4..41.6 && lon in 115.7..117.4 -> "北京市"
            // 上海范围 (30.4-31.9, 120.9-122.0)
            lat in 30.4..31.9 && lon in 120.9..122.0 -> "上海市"
            // 广州范围 (22.4-24.0, 112.9-114.1)
            lat in 22.4..24.0 && lon in 112.9..114.1 -> "广州市"
            // 深圳范围 (22.0-22.9, 113.7-114.8)
            lat in 22.0..22.9 && lon in 113.7..114.8 -> "深圳市"
            // 杭州范围 (29.8-30.9, 119.7-120.9)
            lat in 29.8..30.9 && lon in 119.7..120.9 -> "杭州市"
            // 南京范围 (31.7-32.8, 118.1-119.3)
            lat in 31.7..32.8 && lon in 118.1..119.3 -> "南京市"
            // 武汉范围 (30.0-31.4, 113.7-115.1)
            lat in 30.0..31.4 && lon in 113.7..115.1 -> "武汉市"
            // 成都范围 (30.0-31.4, 103.7-105.1)
            lat in 30.0..31.4 && lon in 103.7..105.1 -> "成都市"
            // 重庆范围 (28.1-32.2, 105.2-110.5)
            lat in 28.1..32.2 && lon in 105.2..110.5 -> "重庆市"
            // 西安范围 (33.5-34.8, 107.9-109.8)
            lat in 33.5..34.8 && lon in 107.9..109.8 -> "西安市"
            // 如果都不匹配，返回GPS定位
            else -> "GPS定位"
        }
    }
    
    /**
     * 检查位置服务是否启用
     */
    private fun isLocationEnabled(): Boolean {
        return locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER) ||
                locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)
    }
    
    /**
     * 判断位置是否更好
     */
    private fun isBetterLocation(location: Location, currentBestLocation: Location?): Boolean {
        if (currentBestLocation == null) {
            return true
        }
        
        // 检查新位置是否比现有位置更新
        val timeDelta = location.time - currentBestLocation.time
        val isSignificantlyNewer = timeDelta > 2 * 60 * 1000 // 2分钟
        val isSignificantlyOlder = timeDelta < -2 * 60 * 1000
        val isNewer = timeDelta > 0
        
        if (isSignificantlyNewer) {
            return true
        } else if (isSignificantlyOlder) {
            return false
        }
        
        // 检查精度
        val accuracyDelta = (location.accuracy - currentBestLocation.accuracy).toInt()
        val isLessAccurate = accuracyDelta > 0
        val isMoreAccurate = accuracyDelta < 0
        val isSignificantlyLessAccurate = accuracyDelta > 200
        
        // 检查提供者是否相同
        val isFromSameProvider = location.provider == currentBestLocation.provider
        
        return when {
            isMoreAccurate -> true
            isNewer && !isLessAccurate -> true
            isNewer && !isSignificantlyLessAccurate && isFromSameProvider -> true
            else -> false
        }
    }
}

data class LocationData(
    val latitude: Double,
    val longitude: Double,
    val city: String = "",
    val district: String = "",
    val address: String = ""
) {
    /**
     * 转换为和风天气API需要的格式 "经度,纬度"
     */
    fun toQWeatherFormat(): String = "$longitude,$latitude"
    
    /**
     * 获取显示名称
     */
    fun getDisplayName(): String {
        return when {
            city.isNotEmpty() && district.isNotEmpty() -> "$city $district"
            city.isNotEmpty() -> city
            address.isNotEmpty() -> address
            else -> getLocationDescription()
        }
    }
    
    /**
     * 获取位置描述
     */
    fun getLocationDescription(): String {
        val latDirection = if (latitude >= 0) "北纬" else "南纬"
        val lonDirection = if (longitude >= 0) "东经" else "西经"
        return "$latDirection${String.format("%.4f", kotlin.math.abs(latitude))}°, " +
                "$lonDirection${String.format("%.4f", kotlin.math.abs(longitude))}°"
    }
} 